package com.zzyl.serve.service.impl;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zzyl.common.constant.CacheConstants;
import com.zzyl.common.constant.HttpStatus;
import com.zzyl.common.core.page.TableDataInfo;
import com.zzyl.common.utils.DateUtils;
import com.zzyl.serve.domain.Device;
import com.zzyl.serve.dto.DeviceDataPageReqDto;
import com.zzyl.serve.dto.DeviceDetailVo;
import com.zzyl.serve.listener.IotMsgHeader;
import com.zzyl.serve.listener.IotMsgNotifyData;
import com.zzyl.serve.listener.IotMsgService;
import com.zzyl.serve.mapper.DeviceMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.zzyl.serve.mapper.DeviceDataMapper;
import com.zzyl.serve.domain.DeviceData;
import com.zzyl.serve.service.IDeviceDataService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

/**
 * 设备数据Service业务层处理
 * 
 * @author Lai
 * @date 2025-08-23
 */
@Slf4j
@Service
public class DeviceDataServiceImpl extends ServiceImpl<DeviceDataMapper, DeviceData> implements IDeviceDataService
{
    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;
    @Autowired
    private DeviceDataMapper deviceDataMapper;

    @Autowired
    private DeviceMapper deviceMapper;

    /**
     * 查询设备数据
     * 
     * @param id 设备数据主键
     * @return 设备数据
     */
    @Override
    public DeviceData selectDeviceDataById(Long id)
    {
        return deviceDataMapper.selectById(id);
    }

    /**
     * 查询设备数据列表
     * 
     * @param deviceData 设备数据
     * @return 设备数据
     */
    @Override
    public List<DeviceData> selectDeviceDataList(DeviceData deviceData)
    {
        return deviceDataMapper.selectDeviceDataList(deviceData);
    }

    /**
     * 新增设备数据
     * 
     * @param deviceData 设备数据
     * @return 结果
     */
    @Override
    public int insertDeviceData(DeviceData deviceData)
    {
        return deviceDataMapper.insert(deviceData);
    }

    /**
     * 修改设备数据
     * 
     * @param deviceData 设备数据
     * @return 结果
     */
    @Override
    public int updateDeviceData(DeviceData deviceData)
    {
        return deviceDataMapper.updateById(deviceData);
    }

    /**
     * 批量删除设备数据
     * 
     * @param ids 需要删除的设备数据主键
     * @return 结果
     */
    @Override
    public int deleteDeviceDataByIds(Long[] ids)
    {
        return deviceDataMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除设备数据信息
     * 
     * @param id 设备数据主键
     * @return 结果
     */
    @Override
    public int deleteDeviceDataById(Long id)
    {
        return deviceDataMapper.deleteById(id);
    }


    /*
    * 批量保存设备
    * */
    @Override
    public void batchSaveDeviceData(IotMsgNotifyData iotMsgNotifyData){
    //获取设备信息
        IotMsgHeader header = iotMsgNotifyData.getHeader();
        Device device =deviceMapper.selectOne(Wrappers.<Device>lambdaQuery().eq(Device::getIotId,header.getDeviceId()));
if(device == null){
    log.error("设备不存在,iotId:{}",header.getDeviceId());
    return;
}

//获取设备上报的数据
// 获取服务列表
        List<IotMsgService> services = iotMsgNotifyData.getBody().getServices();
//遍历每个服务
List<DeviceData> deviceDataList = new ArrayList<>();
for(IotMsgService service : services){
    //获取所有设备的物模型
    Map<String,Object> properties = service.getProperties();
    if(ObjectUtil.isEmpty(properties)){
        return;
    }

    //获取上报时间
    String eventTimeStr = service.getEventTime();
    //转换成LocalDateTime对象 是0时区的时间
    LocalDateTime dateTime = LocalDateTime.parse(eventTimeStr, DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'"));

    //转换成东8时区的localdatetime
    LocalDateTime eventTime = dateTime.atZone(ZoneId.of("UTC")).withZoneSameInstant(ZoneId.of("Asia/Shanghai")).toLocalDateTime();

    //遍历设备的所有物模型数据
    properties.forEach((key, value) -> {
        //创建设备数据对象DeviceData
        DeviceData deviceData = new DeviceData();

        //封装设备上报的数据
        deviceData.setDeviceName(device.getDeviceName());
        deviceData.setIotId(device.getIotId());
        deviceData.setProductKey(device.getProductKey());
        deviceData.setProductName(device.getProductName());
        deviceData.setFunctionId(key);
        deviceData.setAccessLocation(device.getRemark());
        deviceData.setLocationType(device.getLocationType());
        deviceData.setPhysicalLocationType(device.getPhysicalLocationType());
        deviceData.setDeviceDescription(device.getDeviceDescription());
        deviceData.setDataValue(String.valueOf(value));
        deviceData.setAlarmTime(eventTime);

        deviceDataList.add(deviceData);

    });
}

//批量保存设备数据
        saveBatch(deviceDataList);
//↓↓↓将此设备的数据缓存到Redis中。如果Redis中已有数据则直接覆盖，保证Redis中始终只保留最新数据↓↓↓
        redisTemplate.opsForHash().put(CacheConstants.
                IOT_DEVICE_LAST_DATA, device.getIotId(), JSONUtil.toJsonStr(deviceDataList));

    }

    /**
     * 查询设备数据列表
     *
     * @param dto 设备数据
     * @return 设备数据
     */
    @Override
    public TableDataInfo<DeviceData> selectDeviceDataList(DeviceDataPageReqDto dto) {
        //准备查询条件
        LambdaQueryWrapper<DeviceData> wrapper = Wrappers.<DeviceData>lambdaQuery()
                //设备名称模糊查询
                .like(StringUtils.isNotEmpty(dto.getDeviceName()), DeviceData::getDeviceName, dto.getDeviceName())
                //设备属性(功能)精确查询
                .eq(StringUtils.isNotEmpty(dto.getFunctionId()), DeviceData::getFunctionId, dto.getFunctionId())
                //上报时间范围查询
                .between(dto.getStartTime()!=null && dto.getEndTime()!=null, DeviceData::getAlarmTime, dto.getStartTime(), dto.getEndTime());

        //分页查询设备上报的数据
        Page<DeviceData> page = page(Page.of(dto.getPageNum(), dto.getPageSize()), wrapper);

        //封装分页结果
        TableDataInfo<DeviceData> tableDataInfo = new TableDataInfo<>();
        tableDataInfo.setCode(HttpStatus.SUCCESS);
        tableDataInfo.setMsg("操作成功");
        tableDataInfo.setTotal(page.getTotal());
        tableDataInfo.setRows(page.getRecords());
        return tableDataInfo;
    }
}
